OSSで開発メトリクスの計測!GitHub Actionsのissue-metricsを使ってみた
はじめに
今回はGitHub上での開発している際に、開発に関するメトリクスを取ることが出来るGitHub Actionsのissue-metricsについて紹介します。こちらのOSSはGitHubが公式のリポジトリで提供しているものになります。
issue-metricsにはデフォルトで、Pull Requestへの最初のコメントやクローズまでの時間計測などを特定の期間指定してレポートすることが出来ます。それ以外にもラベルと組み合わせることでラベルの付与/削除までの期間計測を利用することでオープンからレビューまでやレビューからapproveまでの時間などのメトリクスを取るような応用も出来ます。
本記事では、サンプルや実際の適用されているOSSの紹介、どんな機能が含まれているのか、どんな応用が可能かをご紹介します。
紹介記事
GitHubのリンク
サンプル
先に何ができるのか例がある方がイメージしやすいと思うので、サンプルを紹介します。最低限の機能を有効化した状態で以下のように、PRのオープンからコメントまでの時間(Time to First Response)、PRのクローズまでの時間(Time to Close)、Discussionsが解決するまでの時間(Time to Answer (Discussions Only))を確認する事ができます。
実際にAWS CDKというOSSでも使用されており、こちらでは月ごとのissue/PRのメトリクスが取られています。
上記のような計測をGitHub Actionsを設定するだけで収集することが出来ます。
どんな機能があるのか
ここからは上記のサンプルなどを元にどんな機能が搭載されているのか記載します。ほぼGitHub上のReadmeの内容に補足を加えています。
Time to First Response
issueやPRに対して、最初にコメントやレビューが付くまでにかかった時間が計測されます。PRやissue単位で計測されるので、個人単位での計測などは現状ありません。また、自分自身のコメントやボットなどのコメントは計測に含まれません。
Time to Close
issue/PRのクローズまでの時間を計測します。
Time to Answer (Discussions Only)
Discussionsの中で作成から回答完了までにかかった時間を計測します。
Time in Label
後述するLABELS_TO_MEASURE
オプションで指定した、ラベルの適用から削除までの期間を計測します。計測するラベルは複数設定することが出来ます。
Time in Labelの応用
基本的な計測は、Time to First Response/Time to Closeなどで計測出来ますが、もう少し多種のメトリクスが取りたくなるかと思います。例えば、PRのレビューやレビューからapproveなどにどこまでの時間をかけているのかです。柔軟な計測を行うために、Time in Labelを使用すれば任意のラベルが付与されて外れるまでの時間を計測できるので、ラベルの自動付与や運用によって様々なメトリクスを取れるようになりそうです。
パラメータ
Actionの中のパラメータ設定を変えることで、出力内容を変えたり、特定のユーザを計測から省くなどの操作が可能です。パラメータを以下に記載します。
項目名 | 値 | 必須か | 値の例 |
---|---|---|---|
GH_TOKEN | リポジトリをスキャンする際に利用するGitHub Token。スキャン対象の全てのリポジトリへの読み取り権限が必要。 | ◯ | ${{ secrets.GITHUB_TOKEN }} や ${{ steps.generate.outputs.token }} など |
SEARCH_QUERY | `repo:owner/repo`または`repo:org/repo`で対象リポジトリ、`is:`でissue/PRのどれを抽出するかや期間などを決める。複数リポジトリの場合は、空白を開けて記載する | ◯ | 'repo:owner/repo repo:owner/repo2 is:issue created:${{ env.last_month }} -reason:"not planned"' |
LABELS_TO_MEASURE | どのラベルを抽出対象とするか記載します。カンマ区切りで複数指定できます。 | 'waiting-for-review,waiting-for-manager' | |
HIDE_AUTHOR | PRやissueの作成者を出力結果から省きます | True OR 任意の値 | HIDE_TIME_TO_FIRST_RESPONSE | 最初の応答時間を出力から省きます | True OR 任意の値 | HIDE_TIME_TO_CLOSE | クローズまでの時間を出力から省きます | True OR 任意の値 | HIDE_TIME_TO_ANSWER | ディスカッションの回答までにかかった時間を出力から省きます | True OR 任意の値 | HIDE_LABEL_METRICS | ラベルに対する計測時間を出力から省きます | True OR 任意の値 | IGNORE_USERS | メトリクスを計測するときに、指定したユーザを除外します。ユーザはカンマ区切りで指定します。 | 'github-actions[bot]' や 'user1,user2' |
設定方法
ここからはGitHub Actionsの設定方法について解説します。
アクションファイルやリポジトリの準備
まずは使用するリポジトリを選択します。ここで選ぶリポジトリは、集計対象のリポジトリでもメトリクス収集用のリポジトリを新しく作っても問題ないです。理由としては、最終的にGitHubのPersonal Access TokenやGitHub Apps Tokenを使用するので、トークン側に読み取る権限があればどこのリポジトリでも問題ないです。
次にメトリクスを取るActionsの設定を考えます。今回はReadmeにも記載れている以下をベースに作成します。他のサンプルはここにあります。
name: Monthly issue metrics on: workflow_dispatch: schedule: - cron: '0 0 1 * *' permissions: issues: write pull-requests: read jobs: build: name: issue metrics runs-on: ubuntu-latest steps: - name: Get dates for last month shell: bash run: | # Calculate the first day of the previous month first_day=$(date -d "last month" +%Y-%m-01) # Calculate the last day of the previous month last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) #Set an environment variable with the date range echo "$first_day..$last_day" echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" - name: Run issue-metrics tool uses: github/issue-metrics@v2 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} SEARCH_QUERY: 'repo:owner/repo is:issue created:${{ env.last_month }} -reason:"not planned"' - name: Create issue uses: peter-evans/create-issue-from-file@v4 with: title: Monthly issue metrics report token: ${{ secrets.GITHUB_TOKEN }} content-filepath: ./issue_metrics.md
内容としては、実行時の前月のissueを抽出し、Time to First Response/Time to Closeなどのデータを抽出して、新規のissueとして書き込みます。書き込みはCreate issue
アクションでサンプルとしてissueに書いているので、別の場所にマークダウンを書き出すように変更もできます。またissue-metrics
アクション自体もPythonで書かれているので、当たり前ですが不便な部分があればissueやPRを上げることも出来ます。
次にSEARCH_QUERY
の部分を修正して、自分のリポジトリやOrgなどが対象になるようにします。今回はrepo:owner/repo
の部分をサンプルリポジトリに変換して試します。
認証トークンの設定
次にGitHub Actionsでデータを読み取りためのトークンを設定します。ソース元のリポジトリでは、Personal Access Tokenを使用していますが、GitHub Apps Tokenでも代替できたのでそちらの方法をご紹介します。以下のブログを参考にしています。
参考元ブログの「1. GitHub Appsを作成する」に沿ってGitHub Appを作成し、リポジトリのステータスやissueなどの権限を設定します。GitHub Actionsの実行には以下の権限で足りました、もう少し権限絞れそうなので、後日わかった際は更新します。
項目名 | 値 |
---|---|
Actions | Read and write |
Commit statuses | Read-only |
Contents | Read-only |
Discussions | Read-only |
Environments | Read-only |
Issues | Read and write |
Metadata | Read-only |
Pull requests | Read-only |
Secrets | Read-only |
Variables | Read-only |
上記で作成した、GitHub AppのAPP_ID/PRIVATE_KEYをActionsを実行するリポジトリのRepository secrets
として登録します。URLはhttps://github.com/{user or org name}/{repository name}/settings/secrets/actions
になります。
参考元では推奨していないですが、今回はサンプルなので手順簡略のためgithub-app-tokenを取得するようにコードを追加/修正します。正式なリポジトリで実行する場合は、自前実装によるGitHub Appsトークンの生成を参考にしてください。
- name: Generate GitHub Apps token id: generate uses: tibdex/github-app-token@v1 with: app_id: ${{ secrets.APP_ID }} private_key: ${{ secrets.PRIVATE_KEY }} - name: Run issue-metrics tool uses: github/issue-metrics@v2 env: GH_TOKEN: ${{ steps.generate.outputs.token }} SEARCH_QUERY: 'repo:owner/repo is:issue created:${{ env.last_month }} -reason:"not planned"'
実行
後は変更した内容をmainブランチに反映するとアクションを実行できるようになります。GitHub Actionsのコードにworkflow-dispatchが設定されているので、cronでの実行タイミング以外でも任意のタイミングで実行できます。
実行すると最初に表示したサンプルのように最低限のメトリクスを見ることが出来ます。
最終的なソースは以下のようになります。
name: Monthly issue metrics on: workflow_dispatch: schedule: - cron: '0 0 1 * *' permissions: issues: write pull-requests: read jobs: build: name: issue metrics runs-on: ubuntu-latest steps: - name: Get dates for last month shell: bash run: | # Calculate the first day of the previous month first_day=$(date +%Y-%m-01) # Calculate the last day of the previous month last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) #Set an environment variable with the date range echo "$first_day..$last_day" echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" - name: Generate GitHub Apps token id: generate uses: tibdex/github-app-token@v1 with: app_id: ${{ secrets.APP_ID }} private_key: ${{ secrets.PRIVATE_KEY }} - name: Run issue-metrics tool uses: github/issue-metrics@v2 env: GH_TOKEN: ${{ steps.generate.outputs.token }} SEARCH_QUERY: 'repo:owner/repo is:issue created:${{ env.last_month }} -reason:"not planned"' - name: Create issue uses: peter-evans/create-issue-from-file@v4 with: title: Monthly issue metrics report token: ${{ secrets.GITHUB_TOKEN }} content-filepath: ./issue_metrics.md
応用例
先程の例だと固定のメトリクスしか取れないです。なので、以下のように自動でラベルを付ける機能と組み合わせて、自分が計測したいタイミングで集計できるか試してみます。今回はissueのラベル単位でラベル付与から削除までのメトリクスを取ってみます。Actionの部分にLABELS_TO_MEASURE
の一行を加えて修正します。
- name: Run issue-metrics tool uses: github/issue-metrics@v2 env: GH_TOKEN: ${{ steps.generate.outputs.token }} SEARCH_QUERY: 'repo:owner/repo is:issue created:${{ env.last_month }} -reason:"not planned"' LABELS_TO_MEASURE: 'bug,sample'
bugラベルはデフォルトのもので、sampleは今回の確認用に独自に追加したものです。これで実行すると以下のように、ラベル単位/PR内のラベル付与から削除までの時間が見れます。
issue単位でも以下のように見えます。(ヘッダが見えなくなるぐらい再試行したので、画像は切り貼りしてます)
issueだけでなく、PRにも設定できるので、PRがマージされるまでの時間以外にも、PR作成からレビューやレビューからapproveまでの時間なども測ることが出来ます。
ついでですが、試しに同じラベルをもう一度付与して削除したところ、最初にラベルが付与された時間から最後にラベルが削除された時間で集計されるようです。
所感
開発のメトリクスを何らか取れないか、GitHubの公式機能で試してみました。試した限りだとまだ機能は少ないですが、ラベルをうまく活用できればそれなりのデータは出せそうです。ただ、現状グラフィカルにする部分などは商用製品の方が質はかなり高いという印象でした。
後、BotによるPRが多いと見にくいので、場合によっては隠したりする処理があると便利そうなので、もう少しソースを理解してフィードバックしてみます。本記事が試して見たかった方の参考になれば幸いです。
製造ビジネステクノロジー部の佐藤智樹でした。